<script setup>
import {
  reactive,
  ref,
  getCurrentInstance,
  watch,
  nextTick,
  onMounted,
  computed,
} from "vue";
import { Toast, ImagePreview } from "vant";
import { useRoute, useRouter, onBeforeRouteLeave } from "vue-router";
import { useStore } from "vuex";
import sendMessage from "@/audios/sendMessage.mp3";
import Emjoi from "@/utils/emjoi";
import { useGetUserInfo } from "@/hooks/chat-hook";
import clone from "@/utils/clone";
let sendUser = null;

const instance = getCurrentInstance();
const store = useStore();
const user = store.state.user.userInfo;
const route = useRoute();
const router = useRouter();
const notify = store.state.notify;
let audioCount = 0;
const app = instance.appContext.app;
let prevAudio = null;
let prevTarget = null;

let nowChats = computed(() => {
  return notify.nowChats;
});

const D = reactive({
  message: "",
  autofocus: false,
  emjoi: "",
  emjois: [],
  msgs: [],
});

let index = ref(0);
let t = null;
let i = 0;

(async () => {
  let chats = (await app.$db.selectAll("chat_record"))[0]?.nowChats;
  if (chats) {
    const currentChatInfoIndex = notify.nowChats.findIndex((v) => {
      return v.id === receiveId && v.id2 === user._id;
    });
    index.value = currentChatInfoIndex;
    if (route.path === "/chat") {
      const now =
        notify.nowChats[currentChatInfoIndex].messages[
          notify.nowChats[currentChatInfoIndex].messages.length - 1
        ];
      if (now) {
        now.readStatus = true;
      }
      store.dispatch("notify/setNowChats", notify.nowChats);
    }
  } else {
    console.log("没有数据");
  }
})();




watch(notify.nowChats, (N) => {
  const currentChatInfoIndex = notify.nowChats.findIndex((v) => {
    return v.id === receiveId && v.id2 === user._id;
  });
  index.value = currentChatInfoIndex;
  if (route.path === "/chat") {
    const now =
      notify.nowChats[currentChatInfoIndex].messages[
        notify.nowChats[currentChatInfoIndex].messages.length - 1
      ];
    if (now) {
      now.readStatus = true;
    }
    store.dispatch("notify/setNowChats", notify.nowChats);
  }
});

onBeforeRouteLeave(async (to, from, next) => {
  nowChats = notify.nowChats;
  const noProxy = clone(nowChats);
  const lines = await app.$db.selectAll("chat_record");
  if (lines.length >= 1) {
    app.$db
      .put("chat_record", {
        id: lines[0]["id"],
        nowChats: noProxy,
      })
      .then((r) => {
        // console.log(r);
      });
  } else {
    app.$db
      .add("chat_record", {
        nowChats: noProxy,
      })
      .then((success) => {})
      .catch((err) => {});
  }
  next();
});

window.onbeforeunload = async function () {
  nowChats = notify.nowChats;
  const noProxy = clone(nowChats);
  const lines = await app.$db.selectAll("chat_record");
  if (lines.length >= 1) {
    app.$db
      .put("chat_record", {
        id: lines[0]["id"],
        nowChats: noProxy,
      })
      .then((r) => {
        // console.log(r);
      });
  } else {
    app.$db
      .add("chat_record", {
        nowChats: noProxy,
      })
      .then((success) => {})
      .catch((err) => {});
  }
};

// 挂载聊天类型
user.type = route.query.type;

const proxy = instance.appContext.config.globalProperties;

const chatType = route.query.type;
const receiveId = route.query.id;

const formatArrayBufferToBlobSrc = (arrayBuffer) => {
  const blobSrc = new Blob([arrayBuffer], {
    type: "image/*",
  });
  return window.URL.createObjectURL(blobSrc);
};

app.$bus.on("setImgsList", (data) => {
  D.msgs.push({
    isImg: true,
    blobSrc: formatArrayBufferToBlobSrc(data),
  });
});

let chatInfo = {
  id: receiveId,
  id2: user._id,
  avatar: "",
  title: "",
  type: chatType,
  messages: [],
};
let chats = [];


(async () => {
  sendUser = (await useGetUserInfo(receiveId))?.data?.u;

  chatInfo.avatar =
    "http://q4.qlogo.cn/headimg_dl?dst_uin=" +
    sendUser.qq_account +
    "&spec=100";
  chatInfo.title = sendUser.nick_name;

  const currentChatInfoIndex = nowChats.value.findIndex(
    (v) => v.id === receiveId && v.id2 === user._id
  );

  if (!nowChats.value[currentChatInfoIndex]) {
    nowChats.value.push(chatInfo);
    store.dispatch("notify/setNowChats", nowChats.value);
  }

  if (nowChats.value.length > 0) {
    const currentChatInfoIndex = nowChats.value.findIndex(
      (v) => v.id === receiveId && v.id2 === user._id
    );
    if (nowChats.value[currentChatInfoIndex]) {
      nowChats.value[currentChatInfoIndex].messages = nowChats.value[
        currentChatInfoIndex
      ]?.messages.map((item) => {
        return (item.readStatus = true) && item;
      });
      let i = 0;
      nowChats.value[currentChatInfoIndex]?.messages
        .filter((v) => {
          return v.isImg;
        })
        .forEach((v) => {
          D.msgs.push({
            isImg: true,
            blobSrc: formatArrayBufferToBlobSrc(v.blobSrc),
          });
        });
    }
  }
})();

// 聊天类型
Toast(chatType);

const emjoi = Emjoi();
const audio = ref(null);
const s_show = ref(false);
const isEmjoi = ref(false);

const showVideo = async (e) => {
  if (prevTarget) prevTarget.classList.remove("rotate");

  const mainBox = document.getElementById("main");

  const file = e.target.files[0];

  if (!file) return;

  const stream = ss.createStream();

  const resource = new Blob([file], {
    type: "video/*",
  });

  const arrayBufferImgSource = await resource.arrayBuffer();

  const message = {
    from: "me",
    date: Date.now(),
    msg: D.message,
    readStatus: true,
    qq: user.qq_account,
    isVideo: true,
    blobSrc: arrayBufferImgSource,
    alt: "[视频]",
  };

  let findChatUIndex = nowChats.value.findIndex((v, i) => {
    return (
      (v.id === sendUser._id || v.id === user._id) &&
      (v.id2 === sendUser._id || v.id2 === user._id)
    );
  });

  if (findChatUIndex >= 0) {
    nowChats.value[findChatUIndex]["messages"].push(message);
  } else {
    nowChats.value.push(chatInfo);
  }

  store.dispatch("notify/setNowChats", nowChats.value);

  nextTick(() => {
    mainBox.scrollTop = mainBox.offsetHeight + mainBox.scrollHeight;
    e.target.value = "";
  });

  // 触发私有消息
  ss(proxy.$socket).emit("private message", stream, {
    channel: receiveId,
    msg: arrayBufferImgSource,
    fromUser: user,
    isVideo: true,
    name: file.name,
  });

  var blobStream = ss.createBlobReadStream(file);

  var size = 0;

  blobStream.on("data", function (chunk) {
    size += chunk.length;
    Toast("发送中 " + Math.floor((size / file.size) * 100) + "%");
  });

  blobStream.on("end", function () {
    Toast.clear();
  });

  blobStream.pipe(stream);
};

const showAudio = async (e) => {
  if (prevTarget) prevTarget.classList.remove("rotate");

  const mainBox = document.getElementById("main");

  let duration;

  const file = e.target.files[0];

  if (!file) return;

  if (file.size / 1204 / 1024 >= 1) {
    return Toast("请发送小于1M的语音");
  }

  const blob = window.URL.createObjectURL(file);

  const resource = new Blob([file]);

  const arrayBufferAudioSource = await resource.arrayBuffer();

  const filelement = new Audio(blob);

  filelement.addEventListener("loadedmetadata", function (_event) {

    duration = parseInt(filelement.duration);
    
    if (duration < 1) {
      return Toast("语音不能小于1秒");
    }

    const message = {
      from: "me",
      date: Date.now(),
      msg: D.message,
      readStatus: true,
      qq: user.qq_account,
      isAudio: true,
      isPlay: false,
      voiceDuration: duration + " “",
      blobSrc: arrayBufferAudioSource,
      alt: "[语音]",
    };

    // chatInfo.messages = [message];

    let findChatUIndex = nowChats.value.findIndex((v, i) => {
      return (
        (v.id === sendUser._id || v.id === user._id) &&
        (v.id2 === sendUser._id || v.id2 === user._id)
      );
    });

    if (findChatUIndex >= 0) {
      nowChats.value[findChatUIndex]["messages"].push(message);
    } else {
      nowChats.value.push(chatInfo);
    }

    store.dispatch("notify/setNowChats", nowChats.value);

    nextTick(() => {
      mainBox.scrollTop = mainBox.offsetHeight + mainBox.scrollHeight;
      e.target.value = "";
    });

    // 触发私有消息
    proxy.$socket.emit("private message", {
      channel: receiveId,
      msg: arrayBufferAudioSource,
      fromUser: user,
      isAudio: true,
      isPlay: false,
      voiceDuration: duration + " “",
    });
  });
};

let flag = false;
let timer = null;

const playVoice = (e, msg, messages) => {
  clearTimeout(timer);
  function commonPart() {
    const tagName = e.target.tagName.toLowerCase();
    if (tagName === "svg") {
      e.target.nextElementSibling.play();
      prevAudio = e.target.nextElementSibling;
      prevTarget = e.target;
      e.target.classList.add("rotate");
    }
  }
  try {
    const audioFirst = messages.reduce((prev, cur) => {
      let i = 0;
      if (cur.isAudio) i = 1;
      return prev + i;
    }, 0);
    if (audioFirst === 1 && prevAudio) {
      if (!flag) {
        commonPart();
        flag = true;
      } else {
        prevAudio.pause();
        if (prevTarget) prevTarget.classList.remove("rotate");
        flag = false;
      }
    } else {
      if (prevAudio) prevAudio.pause();
      if (prevTarget) prevTarget.classList.remove("rotate");
      commonPart();
    }
    timer = setTimeout(() => {
      e.target.classList.remove("rotate");
    }, parseInt(msg.voiceDuration.substring(0, msg.voiceDuration.lastIndexOf(" "))) * 1000);
  } catch (error) {
    Toast(error.message);
  }
};

const showImg = async (e) => {
  const mainBox = document.getElementById("main");

  const file = e.target.files[0];

  if (!file) return;
  if (file.size / 1204 / 1024 >= 1) {
    return Toast("请发送小于1M的表情包或图像");
  }

  const resource = new Blob([file], {
    type: "image/*",
  });

  const arrayBufferImgSource = await resource.arrayBuffer();

  const blob = window.URL.createObjectURL(resource);

  const message = {
    from: "me",
    date: Date.now(),
    msg: D.message,
    readStatus: false,
    qq: user.qq_account,
    isImg: true,
    blobSrc: arrayBufferImgSource,
    alt: "[图片]",
  };

  // chatInfo.messages = [message];

  let findChatUIndex = nowChats.value.findIndex((v, i) => {
    return (
      (v.id === sendUser._id || v.id === user._id) &&
      (v.id2 === sendUser._id || v.id2 === user._id)
    );
  });

  if (findChatUIndex >= 0) {
    nowChats.value[findChatUIndex]["messages"].push(message);
  } else {
    nowChats.value.push(chatInfo);
  }

  store.dispatch("notify/setNowChats", nowChats.value);

  nextTick(() => {
    mainBox.scrollTop = mainBox.offsetHeight + mainBox.scrollHeight;
    e.target.value = "";
  });

  // 触发私有消息
  proxy.$socket.emit("private message", {
    channel: receiveId,
    msg: await resource.arrayBuffer(),
    fromUser: user,
    isImg: true,
  });

  D.msgs.push({
    class: "me",
    blobSrc: blob,
    isImg: true,
  });
};

const on_send = () => {
  const mainBox = document.getElementById("main");

  if (D.message.length <= 0 && D.emjoi.length <= 0) {
    return Toast("消息不能为空");
  }

  s_show.value = false;

  let i = 0;

  D.message = D.emjoi;

  // 替换表情
  D.message = D.message.replace(/\[.*?\]/g, () => {
    const result = D.emjois[i];
    i++;
    return result;
  });

  const message = {
    from: "me",
    date: Date.now(),
    msg: D.message,
    readStatus: true,
    qq: user.qq_account,
  };

  let findChatUIndex = nowChats.value.findIndex((v, i) => {
    return (
      (v.id === sendUser._id || v.id === user._id) &&
      (v.id2 === sendUser._id || v.id2 === user._id)
    );
  });
  if (findChatUIndex >= 0) {
    nowChats.value[findChatUIndex]["messages"].push(message);
  } else {
    nowChats.value.push(chatInfo);
  }

  store.dispatch("notify/setNowChats", nowChats.value);

  nextTick(() => {
    mainBox.scrollTop = mainBox.offsetHeight + mainBox.scrollHeight;
  });

  if (isEmjoi.value) {
    user.isEmjoi = message.isEmjoi = true;
    user.alt = message.alt = D.emjoi;
    isEmjoi.value = false;
  }

  D.msgs.push(message);

  // 触发私有消息
  proxy.$socket.emit("private message", {
    channel: receiveId,
    msg: D.message,
    fromUser: user,
  });

  user.isEmjoi = false;
  user.alt = "";
  audio.value.src = sendMessage;
  audio.value.play();
  setTimeout(() => {
    audio.value.src = "";
  }, 1000);
  D.message = "";
  D.emjoi = "";
  D.emjois = [];
};

const preview = (imgsObj, event) => {
  const arr = [];
  for (let i = 0; i < imgsObj.length; i++) {
    if (imgsObj[i].blobSrc && imgsObj[i].isImg) {
      arr.push(imgsObj[i].blobSrc);
    }
  }
  const markPreviewImgs = document.getElementsByClassName(
    "previewImgClassMark"
  );
  let previewIndex = -1;
  for (let i = 0; i < markPreviewImgs.length; i++) {
    if (markPreviewImgs[i].src === event.target.src) {
      previewIndex = i;
      break;
    }
  }
  ImagePreview({ images: arr, startPosition: previewIndex });
};

const addEmjoi = (emjoi) => {
  isEmjoi.value = true;
  D.emjoi += emjoi.alt;
  D.emjois.push("<img src=" + emjoi.src + " width='25' height='25' />");
  D.message = D.emjoi;
  Toast(emjoi.src);
};

t = setInterval(() => {
    i++;
    document.getElementById("main")?.scrollBy(0,100000)
    if(i > 1){
      clearInterval(t);
      i = 0;
    }
},200)

</script>

<template>
  <div class="chat" id="chat" style="margin-bottom: 50px">
    <van-popup
      v-model:show="s_show"
      position="bottom"
      :style="{ height: '60%' }"
    >
      <van-search
        autofocus
        left-icon
        v-model="D.emjoi"
        show-action
        placeholder="请输入内容,回车发送..."
        @search="on_send"
      >
        <template #action>
          <div @click="on_send">发送</div>
        </template>
      </van-search>
      <div
        v-for="emm in emjoi"
        style="
          display: inline-block;
          width: 20px;
          margin: 5px;
          height: 20px;
          flex-wrap: wrap;
          height: auto;
        "
      >
        <img
          :src="emm.src"
          @click="addEmjoi(emm)"
          width="25"
          height="25"
          alt=""
        />
      </div>
    </van-popup>
    <div class="smile" @click="s_show = true">
      <van-icon name="smile" size="24px" color="#08f" />
    </div>
    <div class="voice" @click="recode_voice">
      <label>
        <input
          @change="showAudio"
          type="file"
          style="display: none"
          accept="audio/*"
          capture="microphone"
        />
        <svg
          t="1651589184251"
          class="icon"
          viewBox="0 0 1024 1024"
          version="1.1"
          xmlns="http://www.w3.org/2000/svg"
          p-id="2066"
          width="24"
          height="24"
        >
          <path
            d="M512 705.728c105.888 0 192-86.112 192-192L704 257.952c0-105.888-86.112-192-192-192s-192 86.112-192 192l0 255.776C320 619.584 406.112 705.728 512 705.728z"
            p-id="2067"
            fill="#0088ff"
          ></path>
          <path
            d="M864 479.776 864 352c0-17.664-14.304-32-32-32s-32 14.336-32 32l0 127.776c0 160.16-129.184 290.464-288 290.464-158.784 0-288-130.304-288-290.464L224 352c0-17.664-14.336-32-32-32s-32 14.336-32 32l0 127.776c0 184.608 140.864 336.48 320 352.832L480 896 288 896c-17.664 0-32 14.304-32 32s14.336 32 32 32l448 0c17.696 0 32-14.304 32-32s-14.304-32-32-32l-192 0 0-63.36C723.136 816.256 864 664.384 864 479.776z"
            p-id="2068"
            class="cursorsHover"
            fill="#0088ff"
          ></path>
        </svg>
      </label>
    </div>
    <div class="photo">
      <label>
        <input
          type="file"
          @change="showImg"
          style="display: none"
          accept="image/*"
        />
        <van-icon name="photo" color="#08f" size="24px" />
      </label>
    </div>
    <div class="video">
      <label>
        <input
          type="file"
          @change="showVideo"
          style="display: none"
          accept="video/*"
        />

        <van-icon name="live" color="#08f" size="24px" />
      </label>
    </div>
    <audio src="" ref="audio"></audio>
    <div
      :class="msg.from === 'other' ? 'other' : 'me'"
      v-for="msg in nowChats[index]?.messages"
    >
      <div class="avatar">
        <img
          :src="'http://q4.qlogo.cn/headimg_dl?dst_uin=' + msg.qq + '&spec=100'"
          alt=""
        />
      </div>
      <div class="message">
        <img
          class="previewImgClassMark"
          :src="formatArrayBufferToBlobSrc(msg.blobSrc)"
          @click="preview(D.msgs, $event)"
          style="width: 80%"
          v-if="msg.isImg"
          alt=""
        />
        <video
          controls
          :src="formatArrayBufferToBlobSrc(msg.blobSrc)"
          style="width: 80%"
          v-if="msg.isVideo"
        />
        <div
          v-if="msg.isAudio"
          class="mark"
          style="background: #08f; padding: 5px; border-radius: 5px"
        >
          <svg
            @click="playVoice($event, msg, nowChats[index]?.messages)"
            t="1651607824339"
            :class="{ icon: true, rotate: msg.isPlay }"
            viewBox="0 0 1024 1024"
            version="1.1"
            xmlns="http://www.w3.org/2000/svg"
            p-id="2066"
            width="20"
            height="20"
          >
            <path
              d="M487.648 240a16 16 0 0 1 16-16h16a16 16 0 0 1 16 16v546.784a16 16 0 0 1-16 16h-16a16 16 0 0 1-16-16V240z m155.84 89.04a16 16 0 0 1 16-16h16a16 16 0 0 1 16 16v346.432a16 16 0 0 1-16 16h-16a16 16 0 0 1-16-16V329.04z m155.824 144.704a16 16 0 0 1 16-16h16a16 16 0 0 1 16 16v123.824a16 16 0 0 1-16 16h-16a16 16 0 0 1-16-16v-123.84z m-467.488-144.704a16 16 0 0 1 16-16h16a16 16 0 0 1 16 16v346.432a16 16 0 0 1-16 16h-16a16 16 0 0 1-16-16V329.04zM176 473.76a16 16 0 0 1 16-16h16a16 16 0 0 1 16 16v112.688a16 16 0 0 1-16 16h-16a16 16 0 0 1-16-16V473.76z"
              p-id="2067"
              class="cursorsHover"
              fill="#ffffff"
            ></path>
          </svg>
          <audio :src="formatArrayBufferToBlobSrc(msg.blobSrc, 1)"></audio>
          {{ msg.voiceDuration }}
        </div>
        <div class="m" v-if="msg.isEmjoi" v-html="msg.msg"></div>
        <div
          v-if="!msg.isImg && !msg.isVideo && !msg.isAudio && !msg.isEmjoi"
          class="m"
        >
          {{ msg.msg }}
        </div>
      </div>
    </div>

    <van-search
      autofocus
      left-icon
      v-model="D.emjoi"
      show-action
      class="sendMessage"
      placeholder="请输入内容,回车发送..."
      @search="on_send"
    >
      <template #action>
        <div @click="on_send">发送</div>
      </template>
    </van-search>
  </div>
</template>

<style lang="scss" scoped>
.chat {
  font: 14px/20px tahoma, arial, "Hiragino Sans GB", "\5b8b\4f53", sans-serif;
  --van-padding-sm: 5px;
  background-color: #eee;
  padding: 10px;
  .sendMessage {
    position: fixed;
    width: 100vw;
    left: 0;
    bottom: 50px;
  }
  .smile,
  .voice,
  .photo,
  .video {
    width: 40px;
    height: 40px;
    background: white;
    justify-content: center;
    position: absolute;
    left: 0;
    border-radius: 0 5px 5px 0;
    display: flex;
    align-items: center;
    z-index: 2;
    &:hover {
      opacity: 0.7;
    }
  }
  .voice {
    bottom: 120px;
  }
  .photo {
    bottom: 200px;
  }
  .video {
    bottom: 280px;
  }
  .smile {
    bottom: 360px;
  }
}

.other,
.me {
  padding: 15px 0;
  display: flex;
  .avatar {
    img {
      width: 50px;
      height: 50px;
      border-radius: 50%;
    }
    margin: 0 10px;
  }
  .message {
    width: auto;
    height: auto;
    color: white;
    text-align: right;
    .m {
      padding: 5px 10px;
      background: #08f;
      min-height: 20px;
      word-wrap: break-word;
    }
  }
}

.other {
  .avatar {
    margin-left: 0;
  }
  .message {
    text-align: left;
  }
}

.me {
  flex-direction: row-reverse;
  .avatar {
    margin-right: 0;
  }
}

.other .message .m,
.me .message .m {
  position: relative;
  border-radius: 5px;
}

.rotate {
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  from {
    transform: rotateX(0deg);
  }
  to {
    transform: rotateX(360deg);
  }
}
</style>
